﻿#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
#include <QFile>
#include <QJsonDocument>
#include <QJsonArray>
#include <QJsonObject>

/*
 * 函数名：Widget
 * 函数说明: 构造函数
 *
 *
 * 输入参数：parent： 父类指针
 * 输出参数：无
 * 返回值：无
 * */
Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    m_publicIconMap[TREE_ITEM_ICON_Project] = QIcon(QStringLiteral(":/treeIcon/res_treeItemIcon/Project.png"));
    m_publicIconMap[TREE_ITEM_ICON_folder] = QIcon(QStringLiteral(":/treeIcon/res_treeItemIcon/folder.png"));
    m_publicIconMap[TREE_ITEM_ICON_folderAnsys] = QIcon(QStringLiteral(":/treeIcon/res_treeItemIcon/folder-ansys.png"));
    m_publicIconMap[TREE_ITEM_ICON_TdmsGroup] = QIcon(QStringLiteral(":/treeIcon/res_treeItemIcon/group.png"));
    m_publicIconMap[TREE_ITEM_ICON_TdmsChannel] = QIcon(QStringLiteral(":/treeIcon/res_treeItemIcon/channel.png"));
    m_publicIconMap[TREE_ITEM_ICON_folderOriginal] = QIcon(QStringLiteral(":/treeIcon/res_treeItemIcon/folder_original.png"));
    m_publicIconMap[TREE_ITEM_ICON_DataItem] = QIcon(QStringLiteral(":/treeIcon/res_treeItemIcon/dataItem.png"));
    initTree();
}

/*
 * 函数名：~Widget
 * 函数说明: 析构函数
 *
 *
 * 输入参数：无
 * 输出参数：无
 * 返回值：无
 * */
Widget::~Widget()
{
    delete ui;
}

/*
 * 函数名：initTree
 * 函数说明: 初始化树形节点数据
 *
 *
 * 输入参数： 无
 * 输出参数：无
 * 返回值：无
 * */
void Widget::initTree()
{
    readData("./treeconfig.json");
//    QStandardItemModel* model = new QStandardItemModel(ui->treeView);
//    model->setHorizontalHeaderLabels(QStringList()<<QStringLiteral("项目名")<<QStringLiteral("信息"));
//    QStandardItem* itemProject = new QStandardItem(m_publicIconMap[QStringLiteral("treeItem_Project")],QStringLiteral("项目"));
//    model->appendRow(itemProject);
//    model->setItem(model->indexFromItem(itemProject).row(),1,new QStandardItem(QStringLiteral("项目信息说明")));
//    QStandardItem* itemFolder = new QStandardItem(m_publicIconMap[QStringLiteral("treeItem_folder")],QStringLiteral("文件夹1"));
//    itemProject->appendRow(itemFolder);
//    itemProject->setChild(itemFolder->index().row(),1,new QStandardItem(QStringLiteral("信息说明")));
//    itemFolder = new QStandardItem(m_publicIconMap[QStringLiteral("treeItem_folder")],QStringLiteral("文件夹2"));
//    itemProject->appendRow(itemFolder);
//    for(int i=0;i<5;++i){
//        QStandardItem* itemgroup = new QStandardItem(m_publicIconMap[QStringLiteral("treeItem_group")],QStringLiteral("组%1").arg(i+1));
//        itemFolder->appendRow(itemgroup);
//        for(int j=0;j<(i+1);++j){
//            QStandardItem* itemchannel = new QStandardItem(m_publicIconMap[QStringLiteral("treeItem_channel")],QStringLiteral("频道%1").arg(j+1));
//            itemgroup->appendRow(itemchannel);
//            itemgroup->setChild(itemchannel->index().row(),1,new QStandardItem(QStringLiteral("频道%1信息说明").arg(j+1)));
//        }
//    }
//    itemProject->setChild(itemFolder->index().row(),1,new QStandardItem(QStringLiteral("文件夹2信息说明")));
//    itemProject = new QStandardItem(m_publicIconMap[QStringLiteral("treeItem_Project")],QStringLiteral("项目2"));
//    model->appendRow(itemProject);
//    for(int i =0;i<3;++i)
//    {
//        itemFolder = new QStandardItem(m_publicIconMap[QStringLiteral("treeItem_folder")],QStringLiteral("项目2文件夹%1").arg(i+1));
//        itemFolder->setCheckable(true);
//        itemFolder->setTristate(true);
//        QStandardItem* itemFolderDes = new QStandardItem(m_publicIconMap[QStringLiteral("treeItem_group")],QStringLiteral("文件夹%1组").arg(i+1));
//        itemProject->appendRow(itemFolder);
//        itemProject->setChild(itemFolder->index().row(),1,itemFolderDes);
//        for(int j=0;j<i+1;++j)
//        {
//             QStandardItem* item = new QStandardItem(m_publicIconMap[QStringLiteral("treeItem_dataItem")],QStringLiteral("项目%1").arg(j+1));
//             item->setCheckable(true);
//             itemFolder->appendRow(item);

//        }
//    }



}


/*
* 函数名：getTopParent
* 函数说明: 获取根部节点，即从属关系的可显示最上级，与invisibleRootItem不同
*
*
* 输入参数： item：需要获取根部节点的节点
* 输出参数：无
* 返回值：QStandardItem* 返回根部节点
* */
QStandardItem* Widget::getTopParent(QStandardItem* item)
{
    QStandardItem* secondItem = item;
    while(item->parent()!= 0)
    {
        secondItem = item->parent();
        item = secondItem;
    }
    if(secondItem->index().column() != 0)
    {
         QStandardItemModel* model = static_cast<QStandardItemModel*>(ui->treeView->model());
         secondItem = model->itemFromIndex(secondItem->index().sibling(secondItem->index().row(),0));
    }
    return secondItem;
}

/*
* 函数名：getTopParent
* 函数说明: 获取根部节点，即从属关系的可显示最上级，与invisibleRootItem不同
*
*
* 输入参数： itemIndex：需要获取根部节点的索引
* 输出参数：无
* 返回值：QStandardItem* 返回根部节点
* */
QModelIndex Widget::getTopParent(QModelIndex itemIndex)
{
    QModelIndex secondItem = itemIndex;
    while(itemIndex.parent().isValid())
    {
        secondItem = itemIndex.parent();
        itemIndex = secondItem;
        if(!(ui->treeView->isExpanded(itemIndex)))
        {
            ui->treeView->setExpanded(itemIndex,true);

        }
    }
    if(secondItem.column() != 0)
    {
         secondItem = secondItem.sibling(secondItem.row(),0);
    }
    return secondItem;
}


/*
* 函数名：on_treeView_clicked
* 函数说明: 点击树列表事件
*
*
* 输入参数： index：当前点击索引
* 输出参数：无
* 返回值：无
* */
void Widget::on_treeView_clicked(const QModelIndex &index)
{
    QString str;
    str += QStringLiteral("当前选中：%1\nrow:%2,column:%3\n").arg(index.data().toString())
            .arg(index.row()).arg(index.column());
    str += QStringLiteral("父级：%1\n").arg(index.parent().data().toString());
    //兄弟节点测试
    QString name,info;
    if(index.column() == 0)
    {
        name = index.data().toString();
        info = index.sibling(index.row(),1).data().toString();
    }
    else
    {
        name = index.sibling(index.row(),0).data().toString();
        info = index.data().toString();
    }
    str += QStringLiteral("名称：%1\n信息：%2\n").arg(name).arg(info);
    //寻找顶层
    QString top = getTopParent(index).data().toString();
    str += QStringLiteral("顶层节点名：%1\n").arg(top);
    ui->label_realTime->setText(str);
}



/*
* 函数名：treeItemChanged
* 函数说明: 树形列表改变事件
*
*
* 输入参数： item:当前改变的节点
* 输出参数：无
* 返回值：无
* */
void Widget::treeItemChanged(QStandardItem * item)
{
    if(item == nullptr)
        return;
    if(item->isCheckable())
    {
        //如果条目是存在复选框的，那么就进行下面的操作
        Qt::CheckState state = item->checkState();//获取当前的选择状态
        if(item->isTristate())
        {
            //如果条目是三态的，说明可以对子目录进行全选和全不选的设置
            if(state != Qt::PartiallyChecked)
            {
                //当前是选中状态，需要对其子项目进行全选
                treeItem_checkAllChild(item,state == Qt::Checked ? true : false);
            }
        }
        else
        {
            //说明是两态的，两态会对父级的三态有影响
            //判断兄弟节点的情况
            treeItem_CheckChildChanged(item);
        }
    }
}


/*
* 函数名：treeItem_checkAllChild
* 函数说明: 递归设置所有的子项目为全选或全不选状态
*
*
* 输入参数： item:当前选中的节点 check true时为全选，false时全不选
* 输出参数：无
* 返回值：无
* */
void Widget::treeItem_checkAllChild(QStandardItem * item, bool check)
{
    if(item == nullptr)
        return;
    int rowCount = item->rowCount();
    for(int i=0;i<rowCount;++i)
    {
        QStandardItem* childItems = item->child(i);
        treeItem_checkAllChild_recursion(childItems,check);
    }
    if(item->isCheckable())
        item->setCheckState(check ? Qt::Checked : Qt::Unchecked);
}

/*
* 函数名：treeItem_checkAllChild_recursion
* 函数说明: 递归设置所有的子项目为全选或全不选状态
*
*
* 输入参数： item:当前选中的节点 check true时为全选，false时全不选
* 输出参数：无
* 返回值：无
* */
void Widget::treeItem_checkAllChild_recursion(QStandardItem * item,bool check)
{
    if(item == nullptr)
        return;
    int rowCount = item->rowCount();
    for(int i=0;i<rowCount;++i)
    {
        QStandardItem* childItems = item->child(i);
        treeItem_checkAllChild_recursion(childItems,check);
    }
    if(item->isCheckable())
        item->setCheckState(check ? Qt::Checked : Qt::Unchecked);
}



/*
* 函数名：treeItem_checkAllChild
* 函数说明: 测量兄弟节点的情况，如果都选中返回Qt::Checked，都不选中Qt::Unchecked,不完全选中返回Qt::PartiallyChecked
*
*
* 输入参数： item:当前改变的节点
* 输出参数：无
* 返回值：如果都选中返回Qt::Checked，都不选中Qt::Unchecked,不完全选中返回Qt::PartiallyChecked
* */
Qt::CheckState Widget::checkSibling(QStandardItem * item)
{
    //先通过父节点获取兄弟节点
    QStandardItem * parent = item->parent();
    if(nullptr == parent)
        return item->checkState();
    int brotherCount = parent->rowCount();
    int checkedCount(0),unCheckedCount(0);
    Qt::CheckState state;
    for(int i=0;i<brotherCount;++i)
    {
        QStandardItem* siblingItem = parent->child(i);
        state = siblingItem->checkState();
        if(Qt::PartiallyChecked == state)
            return Qt::PartiallyChecked;
        else if(Qt::Unchecked == state)
            ++unCheckedCount;
        else
            ++checkedCount;
        if(checkedCount>0 && unCheckedCount>0)
            return Qt::PartiallyChecked;
    }
    if(unCheckedCount>0)
        return Qt::Unchecked;
    return Qt::Checked;
}

/*
* 函数名：treeItem_CheckChildChanged
* 函数说明: 根据子节点的改变，更改父节点的选择情况
*
*
* 输入参数： item:当前改变的节点
* 输出参数：无
* 返回值：无
* */
void Widget::treeItem_CheckChildChanged(QStandardItem * item)
{
    if(nullptr == item)
        return;
    Qt::CheckState siblingState = checkSibling(item);
    QStandardItem * parentItem = item->parent();
    if(nullptr == parentItem)
        return;
    if(Qt::PartiallyChecked == siblingState)
    {
        if(parentItem->isCheckable() && parentItem->isTristate())
            parentItem->setCheckState(Qt::PartiallyChecked);//部分选中
    }
    else if(Qt::Checked == siblingState)
    {
        if(parentItem->isCheckable())
            parentItem->setCheckState(Qt::Checked);//都选中
    }
    else
    {
        if(parentItem->isCheckable())
            parentItem->setCheckState(Qt::Unchecked);//都不选中
    }
    treeItem_CheckChildChanged(parentItem);
}

/*
* 函数名：searchItem
* 函数说明: 递归查找节点
*
*
* 输入参数： index:父节点索引 childCount：子节点数量
* 输出参数：无
* 返回值：无
* */
void Widget::searchItem(const QModelIndex index,int childCount)
{
    QStandardItemModel* model = static_cast<QStandardItemModel*>(ui->treeView->model());

    for(int childNo=0;childNo<childCount;childNo++)
    {
        QModelIndex childIndex = index.child(childNo,0);
        qDebug()<<"parent:"<<childNo<<childCount<<model->data(childIndex).toString();
        if(model->data(childIndex).toString().contains(ui->lineEdit->text()))
        {
            qDebug()<<"####"<<ui->treeView->isExpanded(childIndex);
            getTopParent(childIndex);
//            if(!(ui->treeView->isExpanded(childIndex)))
//            {
//                ui->treeView->setExpanded(childIndex,true);

//            }
        }else{
          ui->treeView->setExpanded(childIndex,false);
        }
        int rowCount = model->rowCount(childIndex);
        if(rowCount>0)
        {
            searchItem(childIndex,rowCount);
        }

    }
}

/*
* 函数名：readData
* 函数说明: 递归解析读取的json文件 加入到model里面
*
*
* 输入参数： filePath:json文件路径
* 输出参数：无
* 返回值：无
* */
void Widget::readData(QString filePath)
{
    QFile file(filePath);
    file.open(QIODevice::ReadOnly);
    QByteArray data = file.readAll();
    QStandardItemModel *model = new QStandardItemModel(ui->treeView);
    model->setHorizontalHeaderLabels(QStringList()<<QStringLiteral("项目名"));
    QStandardItem *parent = model->invisibleRootItem();
    QJsonDocument loadDoc( QJsonDocument::fromJson(data));

    QJsonArray jsonArray;
    qDebug()<<loadDoc.isArray()<<loadDoc.toJson()<<data;
    if(loadDoc.isArray())
    {        
//        QList<TreeItem*> parents;
        jsonArray = loadDoc.array();
        setJsonData(jsonArray,parent);
    }

    //关联项目属性改变的信号和槽
    connect(model,&QStandardItemModel::itemChanged,this,&Widget::treeItemChanged);
    //connect(model,SIGNAL(itemChanged(QStandardItem*)),this,SLOT(treeItemChanged(QStandardItem*)));
    ui->treeView->setModel(model);


}

/*
* 函数名：setJsonData
* 函数说明: 递归函数 把json数据加入到model
*
*
* 输入参数： jsonArray:json格式的数组 parent：数组的父节点
* 输出参数：无
* 返回值：无
* */
void Widget::setJsonData(QJsonArray &jsonArray, QStandardItem *parent)
{
    for (int i = 0; i < jsonArray.size(); ++i) {
        QJsonValue jsonValue= jsonArray[i];
       if(jsonValue.type() == QJsonValue::Object)
       {
          QJsonObject childObject = jsonValue.toObject() ;
          if(childObject.contains("name")){
              QString  name = childObject.value("name").toString();
              QStandardItem* item = new QStandardItem(QIcon(QStringLiteral(":/treeIcon/res_treeItemIcon/dataItem.png")),name);
              item->setCheckable(true);
              parent->appendRow(item);           
              //parent->appendChild(new TreeItem(name, parent));
          }
          if(childObject.contains("child"))
          {
              parent->child(parent->rowCount()-1)->setTristate(true);
              parent->child(parent->rowCount()-1)->setIcon(QIcon(QStringLiteral(":/treeIcon/res_treeItemIcon/Project.png")));
              QJsonArray childArray = childObject.value("child").toArray();
              setJsonData(childArray,parent->child(parent->rowCount()-1));
          }
        }
    }
}



/*
 * 函数名：on_pBtn_collapseAll_clicked
 * 函数说明: 折叠全部节点
 *
 *
 * 输入参数： 无
 * 输出参数：无
 * 返回值：无
 * */
void Widget::on_pBtn_collapseAll_clicked()
{
    ui->treeView->collapseAll();
}


/*
 * 函数名：on_pBtn_expandAll_clicked
 * 函数说明: 展开全部节点
 *
 *
 * 输入参数： 无
 * 输出参数：无
 * 返回值：无
 * */
void Widget::on_pBtn_expandAll_clicked()
{
    ui->treeView->expandAll();
}

/*
 * 函数名：on_pBtn_search_clicked
 * 函数说明: 查找节点
 *
 *
 * 输入参数： 无
 * 输出参数：无
 * 返回值：无
 * */
void Widget::on_pBtn_search_clicked()
{
    QStandardItemModel* model = static_cast<QStandardItemModel*>(ui->treeView->model());
//    QModelIndex currentIndex = ui->treeView->currentIndex();
//    QStandardItem* currentItem = model->itemFromIndex(currentIndex);
//    ui->label_2->setText(getTopParent(currentItem)->text());
    for(int row =0;row<model->rowCount();row++)
    {
        QModelIndex index= model->index(row,0);
        int rowcount = model->rowCount(index);
        qDebug()<<model->rowCount(index)<<model->data(index);
        searchItem(index,rowcount);
    }
}
